#!/usr/bin/env python3
"""Check if any function nodes within OrderTemplate.java invoke getSupplierInfo"""

import pickle
import networkx as nx
from neo4j import GraphDatabase

# Load the original graph
print("Loading original graph...")
with open('business-payout.pkl', 'rb') as f:
    G = pickle.load(f)

file_node = 'business-payout-biz/src/main/java/com/pingpongx/business/payout/biz/service/core/OrderTemplate.java'
target_function = 'getSupplierInfo'

print(f"\n=== Analyzing file structure in NetworkX Graph ===")
print(f"File: {file_node}")

if file_node in G:
    # Find all nodes contained in this file
    contained_nodes = []
    for source, target, data in G.out_edges(file_node, data=True):
        if data.get('type') == 'contains':
            contained_nodes.append(target)

    print(f"\nNodes directly contained in this file: {len(contained_nodes)}")

    # Categorize contained nodes by type
    classes = []
    functions = []
    other = []

    for node in contained_nodes:
        if node in G:
            node_attrs = G.nodes[node]
            node_type = node_attrs.get('type', 'unknown')
            if node_type == 'class':
                classes.append(node)
            elif node_type == 'function':
                functions.append(node)
            else:
                other.append(node)

    print(f"  Classes: {len(classes)}")
    print(f"  Functions: {len(functions)}")
    print(f"  Other: {len(other)}")

    # Check classes for contained functions
    all_functions = functions.copy()
    for class_node in classes:
        print(f"\n  Class: {class_node}")
        # Find functions contained in this class
        for source, target, data in G.out_edges(class_node, data=True):
            if data.get('type') == 'contains':
                if G.nodes[target].get('type') == 'function':
                    all_functions.append(target)
                    print(f"    Contains function: {target}")

    print(f"\nTotal functions found: {len(all_functions)}")

    # Check if any function invokes getSupplierInfo
    print(f"\nChecking invocations from functions:")
    found_invocations = []

    for func in all_functions:
        if func in G:
            # Check outgoing invokes edges
            for source, target, data in G.out_edges(func, data=True):
                if data.get('type') == 'invokes':
                    if target_function in target:
                        found_invocations.append((func, target))
                        print(f"  ✅ {func} -> {target}")

    if not found_invocations:
        print(f"  ❌ No functions invoke {target_function}")

        # Show what functions DO invoke (sample)
        print(f"\n  Sample of actual invocations:")
        invocation_count = 0
        for func in all_functions[:5]:  # Check first 5 functions
            if func in G:
                invokes = []
                for source, target, data in G.out_edges(func, data=True):
                    if data.get('type') == 'invokes':
                        invokes.append(target)
                if invokes:
                    print(f"    {func} invokes:")
                    for inv in invokes[:3]:
                        print(f"      -> {inv}")
                    invocation_count += len(invokes)

        print(f"\n  Total invocations from all functions: {invocation_count}")

else:
    print(f"File node not found in graph!")

# Check in Neo4j
print(f"\n=== Checking in Neo4j Database ===")

driver = GraphDatabase.driver("bolt://localhost:5018", auth=("neo4j", "neo4j123"))

with driver.session() as session:
    # Find all nodes contained in the file (recursively)
    result = session.run("""
        MATCH (file:Node {id: $file_id})-[:CONTAINS*]->(contained:Node)
        WHERE contained.type IN ['function', 'class']
        RETURN contained.id, contained.type, contained.degree
        ORDER BY contained.type, contained.id
    """, file_id=file_node)

    contained_nodes = list(result)
    print(f"\nNodes contained in file (recursively): {len(contained_nodes)}")

    classes = [n for n in contained_nodes if n['contained.type'] == 'class']
    functions = [n for n in contained_nodes if n['contained.type'] == 'function']

    print(f"  Classes: {len(classes)}")
    print(f"  Functions: {len(functions)}")

    # Show the contained nodes
    if classes:
        print(f"\nClasses in this file:")
        for node in classes[:5]:
            print(f"  - {node['contained.id']}")

    if functions:
        print(f"\nFunctions in this file:")
        for node in functions[:10]:
            print(f"  - {node['contained.id']}")
        if len(functions) > 10:
            print(f"  ... and {len(functions)-10} more")

    # Check if any contained function invokes getSupplierInfo
    result = session.run("""
        MATCH (file:Node {id: $file_id})-[:CONTAINS*]->(func:Node {type: 'function'})
        MATCH (func)-[:INVOKES]->(target:Node)
        WHERE target.id CONTAINS $function_name
        RETURN func.id as invoker, target.id as invoked
    """, file_id=file_node, function_name=target_function)

    invocations = list(result)
    if invocations:
        print(f"\n✅ Found {len(invocations)} invocations of {target_function}:")
        for inv in invocations:
            print(f"  {inv['invoker']} -> {inv['invoked']}")
    else:
        print(f"\n❌ No functions in this file invoke {target_function}")

    # Check total invocations from all functions in this file
    result = session.run("""
        MATCH (file:Node {id: $file_id})-[:CONTAINS*]->(func:Node {type: 'function'})
        MATCH (func)-[:INVOKES]->(target:Node)
        RETURN count(*) as count
    """, file_id=file_node)

    total_invokes = result.single()['count']
    print(f"\nTotal INVOKES relationships from functions in this file: {total_invokes}")

    # Show sample of what functions DO invoke
    if total_invokes > 0:
        result = session.run("""
            MATCH (file:Node {id: $file_id})-[:CONTAINS*]->(func:Node {type: 'function'})
            MATCH (func)-[:INVOKES]->(target:Node)
            RETURN func.id as invoker, target.id as invoked
            LIMIT 10
        """, file_id=file_node)

        print(f"\nSample of actual invocations:")
        for record in result:
            print(f"  {record['invoker']}")
            print(f"    -> {record['invoked']}")

driver.close()

print("\n=== Summary ===")
print(f"Analyzed structure of {file_node}")
print(f"Searched for invocations of '{target_function}' from contained functions")
print("Note: The presence of invokes edges depends on how the graph was built.")